/**
 *
 */
package co.fitstart.admin.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.demo2do.core.BusinessException;
import com.demo2do.core.persistence.annotation.Dynamic;
import com.demo2do.core.support.Page;
import com.demo2do.core.utils.SignatureUtils;

import co.fitstart.admin.dao.PrincipalDao;
import co.fitstart.admin.dao.SiteDao;
import co.fitstart.admin.entity.search.PrincipalSearch;
import co.fitstart.admin.handler.TencentHandler;
import co.fitstart.admin.service.PrincipalService;
import co.fitstart.entity.coach.PrincipalReportRelation;
import co.fitstart.entity.principal.Principal;
import co.fitstart.entity.principal.PrincipalType;
import co.fitstart.entity.site.Site;

/**
 * @author Downpour
 * @author Leo
 */
@Service("principalService")
public class PrincipalServiceImpl extends DataServiceImpl<Principal> implements PrincipalService {

    @Dynamic
    private PrincipalDao principalDao;
    
    @Dynamic SiteDao siteDao;

    @SuppressWarnings("unused")
	@Autowired
    private TencentHandler tencentHandler;

    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#list(co.fitstart.entity.principal.PrincipalType, com.demo2do.core.support.Page)
     */
    public List<Principal> list(PrincipalType type, Page page) {
        List<Principal> result = principalDao.list(type, page.getBeginIndex(), page.getMaxResultRecords());
        page.calculate(result.size());
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#searchForAdminAndRoot(co.fitstart.admin.entity.search.PrincipalSearch, com.demo2do.core.support.Page)
     */
    @SuppressWarnings("unchecked")
    public List<Principal> searchForAdminOrRoot(PrincipalSearch principalSearch, Page page) {
        String s = principalSearch.buildSentenceTemplate();
        Map<String, Object> parameters = principalSearch.buildParameters();
        
        List<Principal> result = new ArrayList<>();
        
        if(principalSearch.getSites() == null || principalSearch.getAuthority() != null) {
            result = genericDaoSupport.searchForList(s, parameters, page.getBeginIndex(), page.getMaxResultRecords());
        } else {
            //list AreaManager
            List<Principal> areaManagers = this.searchAreaManager(principalSearch.getSites().get(0),
                    principalSearch.getName(), principalSearch.getDisabled(), page.getBeginIndex(), page.getMaxResultRecords());
            
            result.addAll(areaManagers);
            
            //list AreaServer
            if(result.size() < page.getMaxResultRecords()) {
                int areaManagerCount = this.countAreaManager(principalSearch.getSites().get(0),
                        principalSearch.getName(), principalSearch.getDisabled());
                
                List<Principal> areaServers = this.searchAreaServer(principalSearch.getSites().get(0),
                        principalSearch.getName(), principalSearch.getDisabled(),
                        page.getBeginIndex() - areaManagerCount, page.getMaxResultRecords() - areaManagerCount);
                
                result.addAll(areaServers);
                
                //list SiteManager
                if(result.size() < page.getMaxResultRecords()) {
                    
                    int areaServerCount = this.countAreaServer(principalSearch.getSites().get(0),
                            principalSearch.getName(), principalSearch.getDisabled());
                    
                    List<Principal> siteManagers = this.searchSiteManager(principalSearch.getSites(),
                            principalSearch.getName(), principalSearch.getDisabled(),
                            page.getBeginIndex() - areaManagerCount - areaServerCount, page.getMaxResultRecords() - result.size());
                    
                    result.addAll(siteManagers);
                    
                    //list Coach and SiteServer
                    if(result.size() < page.getMaxResultRecords()) {
                        int siteManagerCount = this.countSiteManager(principalSearch.getSites(),
                                principalSearch.getName(), principalSearch.getDisabled());
                        
                        List<Principal> coachAndSiteServers = genericDaoSupport.searchForList(s, parameters,
                                page.getBeginIndex() - areaManagerCount - areaServerCount - siteManagerCount, page.getMaxResultRecords() - result.size());
                        
                        result.addAll(coachAndSiteServers);
                    }
                }
            }
        }
        
        page.calculate(result.size());
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }
    
    /**
     * 
     * @param site
     * @param name
     * @param disabled
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @SuppressWarnings("unchecked")
    private List<Principal> searchAreaManager(Site site, String name, Boolean disabled, int beginIndex, int maxResult) {
        StringBuffer sentence = new StringBuffer("SELECT site.areaManager FROM Site site WHERE site =:site");
        
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("site", site);
        
        if(name != null) {
            sentence.append(" AND site.areaManager.name LIKE :name");
            parameters.put("name", "%" + name + "%");
        }
        
        if(disabled != null) {
            sentence.append(" AND site.areaManager.disabled =:disabled");
            parameters.put("disabled", disabled);
        }
        
        return genericDaoSupport.searchForList(sentence.toString(), parameters, beginIndex, maxResult);
    }
    
    /**
     * 
     * @param site
     * @param name
     * @param disabled
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @SuppressWarnings("unchecked")
    private List<Principal> searchAreaServer(Site site, String name, Boolean disabled, int beginIndex, int maxResult) {
        StringBuffer sentence = new StringBuffer("SELECT site.areaServer FROM Site site WHERE site =:site");
        
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("site", site);
        
        if(name != null) {
            sentence.append(" AND site.areaServer.name LIKE :name");
            parameters.put("name", "%" + name + "%");
        }
        
        if(disabled != null) {
            sentence.append(" AND site.areaServer.disabled =:disabled");
            parameters.put("disabled", disabled);
        }
        
        return genericDaoSupport.searchForList(sentence.toString(), parameters, beginIndex, maxResult);
    }
    
    /**
     * 
     * @param site
     * @param name
     * @param disabled
     * @param beginIndex
     * @param maxResult
     * @return
     */
    private int countAreaManager(Site site, String name, Boolean disabled) {
        StringBuffer sentence = new StringBuffer("SELECT site.areaManager FROM Site site WHERE site =:site");
        
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("site", site);
        
        if(name != null) {
            sentence.append(" AND site.areaManager.name LIKE :name");
            parameters.put("name", "%" + name + "%");
        }
        
        if(disabled != null) {
            sentence.append(" AND site.areaManager.disabled =:disabled");
            parameters.put("disabled", disabled);
        }
        
        return genericDaoSupport.count(sentence.toString(), parameters);
    }
    
    /**
     * 
     * @param site
     * @param name
     * @param disabled
     * @return
     */
    private int countAreaServer(Site site, String name, Boolean disabled) {
        StringBuffer sentence = new StringBuffer("SELECT site.areaServer FROM Site site WHERE site =:site");
        
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("site", site);
        
        if(name != null) {
            sentence.append(" AND site.areaServer.name LIKE :name");
            parameters.put("name", "%" + name + "%");
        }
        
        if(disabled != null) {
            sentence.append(" AND site.areaServer.disabled =:disabled");
            parameters.put("disabled", disabled);
        }
        
        return genericDaoSupport.count(sentence.toString(), parameters);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#searchForAreaManager(co.fitstart.admin.entity.search.PrincipalSearch, com.demo2do.core.support.Page)
     */
    @SuppressWarnings("unchecked")
    public List<Principal> searchForAreaManager(PrincipalSearch principalSearch, Page page) {
        String s = principalSearch.buildSentenceTemplate();
        Map<String, Object> parameters = principalSearch.buildParameters();
        
        List<Principal> result = new ArrayList<>();
        
        if(principalSearch.getAuthority() != null) {
            result = genericDaoSupport.searchForList(s, parameters, page.getBeginIndex(), page.getMaxResultRecords());
        } else {
            //list SiteManager
            List<Principal> siteManagers = this.searchSiteManager(principalSearch.getSites(),
                    principalSearch.getName(), principalSearch.getDisabled(),
                    page.getBeginIndex(), page.getMaxResultRecords());
            
            result.addAll(siteManagers);
            
            //list Coach and SiteServer
            if(result.size() < page.getMaxResultRecords()) {
                int siteManagerCount = this.countSiteManager(principalSearch.getSites(),
                        principalSearch.getName(), principalSearch.getDisabled());
                
                List<Principal> coachAndSiteServers = genericDaoSupport.searchForList(s, parameters,
                        page.getBeginIndex() - siteManagerCount, page.getMaxResultRecords() - result.size());
                
                result.addAll(coachAndSiteServers);
            }
        }
        
        page.calculate(result.size());
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }
    
    /**
     * 
     * @param sites
     * @param name
     * @param disabled
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @SuppressWarnings("unchecked")
    private List<Principal> searchSiteManager(List<Site> sites, String name, Boolean disabled, int beginIndex, int maxResult) {
        StringBuffer sentence = new StringBuffer("SELECT relation.manager FROM PrincipalReportRelation relation WHERE relation.coach IS NULL AND relation.site IN (:sites)");
        
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("sites", sites);
        
        if(name != null) {
            sentence.append(" AND relation.manager.name LIKE :name");
            parameters.put("name", "%" + name + "%");
        }
        
        if(disabled != null) {
            sentence.append(" AND relation.manager.disabled =:disabled");
            parameters.put("disabled", disabled);
        }
        
        return genericDaoSupport.searchForList(sentence.toString(), parameters, beginIndex, maxResult);
    }
    
    /**
     * 
     * @param sites
     * @param name
     * @param disabled
     * @return
     */
    private int countSiteManager(List<Site> sites, String name, Boolean disabled) {
        StringBuffer sentence = new StringBuffer("SELECT manager FROM PrincipalReportRelation WHERE coach IS NULL AND site IN (:sites)");
        
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("sites", sites);
        
        if(name != null) {
            sentence.append(" AND manager.name LIKE :name");
            parameters.put("name", "%" + name + "%");
        }
        
        if(disabled != null) {
            sentence.append(" AND manager.disabled =:disabled");
            parameters.put("disabled", disabled);
        }
        
        return genericDaoSupport.count(sentence.toString(), parameters);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#searchForSiteManager(co.fitstart.admin.entity.search.PrincipalSearch, com.demo2do.core.support.Page)
     */
    @SuppressWarnings("unchecked")
    public List<Principal> searchForSiteManagerOrAreaServer(PrincipalSearch principalSearch, Page page) {
        String s = principalSearch.buildSentenceTemplate();
        Map<String, Object> parameters = principalSearch.buildParameters();
        List<Principal> result = genericDaoSupport.searchForList(s, parameters, page.getBeginIndex(), page.getMaxResultRecords());
        page.calculate(result.size());
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#search(co.fitstart.admin.entity.search.PrincipalSearch, com.demo2do.core.support.Page)
     */
    @SuppressWarnings("unchecked")
    public List<Principal> search(PrincipalSearch principalSearch, Page page) {
        String s = principalSearch.buildSentenceTemplate();
        Map<String, Object> parameters = principalSearch.buildParameters();
        List<Principal> result = genericDaoSupport.searchForList(s, parameters, page.getBeginIndex(), page.getMaxResultRecords());
        page.calculate(result.size());
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#list(boolean, co.fitstart.entity.principal.PrincipalType, com.demo2do.core.support.Page)
     */
    public List<Principal> list(boolean code, PrincipalType type, Page page) {
        List<Principal> result = new ArrayList<Principal>();
        if (code) {
            result = principalDao.listUnEmptyCodePrincipal(type, page.getBeginIndex(), page.getMaxResultRecords());
        } else {
            result = principalDao.listEmptyCodePrincipal(type, page.getBeginIndex(), page.getMaxResultRecords());
        }
        
        page.calculate(result.size());
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }

    /* (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#listRelation(co.fitstart.entity.site.Site, com.demo2do.core.support.Page)
     */
    public List<PrincipalReportRelation> listRelation(Site site, Page page) {
        List<PrincipalReportRelation> result = principalDao.listRelation(site, page.getBeginIndex(), page.getMaxResultRecords());
        page.calculate(result.size());
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#list(java.util.List, com.demo2do.core.support.Page)
     */
    public List<Principal> listForAreaManager(List<Site> sites, Page page) {
        List<Principal> siteManagers = principalDao.listSiteManager(sites, page.getBeginIndex(), page.getMaxResultRecords());
        if(siteManagers.size() == page.getMaxResultRecords()) {
            page.calculate(siteManagers.size());
            return siteManagers.subList(0, page.getEveryPage());
        } else {
            long siteManagerCount = principalDao.getSiteManagerCount(sites);
            
            List<Principal> others = principalDao.listCoachAndSiteServer(sites, page.getBeginIndex() - (int)siteManagerCount, page.getMaxResultRecords() - siteManagers.size());
            
            siteManagers.addAll(others);
            
            page.calculate(siteManagers.size());
            return siteManagers.size() > page.getEveryPage() ? siteManagers.subList(0, page.getEveryPage()) : siteManagers;
        }
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#listForAreaServer(java.util.List, com.demo2do.core.support.Page)
     */
    public List<Principal> listForAreaServer(List<Site> sites, Page page) {
        List<Principal> result = principalDao.listCoachAndSiteServer(sites, page.getBeginIndex(), page.getMaxResultRecords());
        page.calculate(result.size());
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#searchRelation(co.fitstart.admin.entity.search.PrincipalSearch, com.demo2do.core.support.Page)
     */
    @SuppressWarnings("unchecked")
    public List<PrincipalReportRelation> searchRelation(PrincipalSearch principalSearch, Page page) {
        String s = principalSearch.buildSentenceTemplate();
        Map<String, Object> parameters = principalSearch.buildParameters();
        List<PrincipalReportRelation> result = genericDaoSupport.searchForList(s, parameters, page.getBeginIndex(), page.getMaxResultRecords());
        page.calculate(result.size());
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }

    /* (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#listRelation(co.fitstart.entity.principal.Principal)
     */
    public List<PrincipalReportRelation> listRelation(Principal coach) {
        return principalDao.listRelation(coach);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#loadRelation(co.fitstart.entity.principal.Principal, co.fitstart.entity.principal.Principal)
     */
    public PrincipalReportRelation loadRelation(Principal coach, Principal manager) {
        return principalDao.getRelation(coach, manager);
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#editRelation(co.fitstart.entity.principal.Principal, java.util.List)
     */
    public void editRelation(Principal coach, List<Long> relationIds) {
        List<PrincipalReportRelation> originalrelations = principalDao.listRelation(coach);
        
        List<PrincipalReportRelation> relations = new ArrayList<>();
        
        //add new
        for(Long id : relationIds) {
            PrincipalReportRelation managerSiteRelation = genericDaoSupport.load(PrincipalReportRelation.class, id);

            Principal manager = managerSiteRelation.getManager();
            Site site = managerSiteRelation.getSite();
            
            PrincipalReportRelation relation = principalDao.getRelation(coach, manager);
            
            if(relation == null) {
                relation = new PrincipalReportRelation(coach, manager, site);
                genericDaoSupport.save(relation);
            } else {
                relations.add(relation);
            }
        }
        
        //delete old
        for(PrincipalReportRelation relation : originalrelations) {
            if(!relations.contains(relation)) {
                principalDao.deteleRelation(relation.getCoach(), relation.getManager());
            }
        }
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#create(co.fitstart.entity.principal.Principal)
     */
    public void create(Principal principal) {
        genericDaoSupport.save(principal.initialize(PrincipalType.NORMAL));
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#createCoach(co.fitstart.entity.principal.Principal, java.lang.String, co.fitstart.entity.principal.Principal)
     */
    public void createCoach(Principal coach, String weixinid, Principal manager) {

        // 1 create principal
        genericDaoSupport.save(coach.initialize(PrincipalType.SITE));

        // 2 create new coachRelation
        Site site = principalDao.getRelation(manager.getId()).getSite();

        PrincipalReportRelation relation = new PrincipalReportRelation(coach, manager, site);
        genericDaoSupport.save(relation);

        // 3 add coach's salary
//        if(coachSalaries != null) {
//
//            for(String coachSalaryItem : coachSalaries) {
//
//                String[] result = StringUtils.split(coachSalaryItem, "|");
//
//                if(result.length != 2) {
//                    throw new BusinessException("教练工资输入有误");
//                }
//
//                try {
//
//                    Long courseId = new Long(result[0]);
//                    Course course = genericDaoSupport.load(Course.class, courseId);
//
//                    BigDecimal settlement = new BigDecimal(result[1]);
//
//                    CoachSettlement coachSettlement = new CoachSettlement(coach, course, settlement);
//                    genericDaoSupport.save(coachSettlement);
//
//                } catch(Exception e) {
//
//                    throw new BusinessException("教练工资输入有误");
//
//                }
//
//            }
//        }

        // STEP4 if is enterprise, create corp user
//        if(coach.isEnterprise()) {
//            
//            String mobile = coach.getMobile();
//            String name = coach.getName();
//
//            Result result = tencentHandler.createUser(mobile, mobile, weixinid, name);
//
//            if(!result.isValid()) {
//                throw new BusinessException(result.getMessage());
//            }
//        }
    }

    /* (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#createSiteAssist(co.fitstart.entity.principal.Principal, co.fitstart.entity.site.Site)
     */
    public void createSiteAssist(Principal siteAssist, Site site) {

        // 1 create principal
        genericDaoSupport.save(siteAssist.initialize(PrincipalType.SITE));

        // Step2 save new coachRelation
        PrincipalReportRelation coachRelation = new PrincipalReportRelation(siteAssist, site);
        genericDaoSupport.save(coachRelation);

    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#changePassword(co.fitstart.admin.entity.security.Principal, java.lang.String)
     */
    public void changePassword(Principal principal, String password) {
        if(SignatureUtils.makeMD5Signature(password).equals(principal.getPassword())) {
            throw new BusinessException("新密码不能与原密码相同");
        }
        genericDaoSupport.update(principal.changePassword(password));
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#resetPassword(co.fitstart.admin.entity.security.Principal)
     */
    public void resetPassword(Principal principal) {
        genericDaoSupport.update(principal.resetPassword());
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#getRelation(co.fitstart.entity.principal.Principal)
     */
    public PrincipalReportRelation getRelation(Principal principal) {
        return principalDao.getSiteRelation(principal);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#listSiteManager()
     */
    public Map<Long, Principal> listSiteManager() {
        List<PrincipalReportRelation> relations = principalDao.listSiteManager();
        Map<Long, Principal> result = new HashMap<Long, Principal>();
        for(PrincipalReportRelation relation : relations) {
            result.put(relation.getSite().getId(), relation.getManager());
        }
        return result;
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#loadSiteManager(co.fitstart.entity.site.Site)
     */
    public Principal loadSiteManager(Site site) {
        PrincipalReportRelation principalReportRelation = principalDao.getSiteManager(site);
        return principalReportRelation == null ? null : principalReportRelation.getManager();
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#createAreaManager(co.fitstart.entity.principal.Principal, java.util.List)
     */
    public void createAreaManager(Principal areaManager, List<Site> sites) {
        genericDaoSupport.save(areaManager.initializeAreaManager().resetPassword());
        
        for(Site site : sites) {
            genericDaoSupport.update(site.editAreaManager(areaManager));
        }
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#editManagedSites(co.fitstart.entity.principal.Principal, java.util.List)
     */
    public void editManagedSites(Principal principal, List<Site> sites) {
        if(principal.isAreaManager()) {
            List<Site> originalSites = siteDao.listSitesForAreaManager(principal);
                    
            for(Site site : originalSites) {
                genericDaoSupport.update(site.editAreaManager(null));
            }
            
            for(Site site : sites) {
                genericDaoSupport.update(site.editAreaManager(principal));
            }
        } else if(principal.isAreaServer()) {
            List<Site> originalSites = siteDao.listSitesForAreaServer(principal);
            
            for(Site site : originalSites) {
                genericDaoSupport.update(site.editAreaServer(null));
            }
            
            for(Site site : sites) {
                genericDaoSupport.update(site.editAreaServer(principal));
            }
        }
        
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#loadRelation(co.fitstart.entity.principal.Principal)
     */
    public PrincipalReportRelation loadRelation(Principal principal) {
        if(principal.isSiteManager()) {
            return principalDao.getRelation(principal.getId());
        } else if(principal.isSiteServer()) {
            return principalDao.getBySiteServer(principal);
        } else {
            return null;
        }
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#createAreaServer(co.fitstart.entity.principal.Principal, java.util.List)
     */
    public void createAreaServer(Principal areaServer, List<Site> sites) {
        Principal principal = principalDao.load(areaServer.getName());
        
        if(principal == null) {
            genericDaoSupport.save(areaServer.initializeAreaServer().resetPassword());
            
            for(Site site : sites) {
                genericDaoSupport.update(site.editAreaServer(areaServer));
            }
        } else {
            throw new BusinessException("已存在用户名为" + areaServer.getName() + "的账号");
        }
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#createSiteManager(co.fitstart.entity.principal.Principal, co.fitstart.entity.site.Site)
     */
    public void createSiteManager(Principal siteManager, Site site) {
        Principal principal = principalDao.load(siteManager.getName());
        
        if(principal != null) {
            throw new BusinessException("已存在用户名为" + siteManager.getName() + "的账号");
        } else {
            genericDaoSupport.save(siteManager.initializeSiteManager().resetPassword());
            
            PrincipalReportRelation relation = principalDao.getSiteManager(site);
            if(relation == null) {
                genericDaoSupport.save(new PrincipalReportRelation(null, siteManager, site));
            } else {
                relation.getManager().disabled();
            }
            
            principalDao.updateSiteManager(siteManager, site);
            genericDaoSupport.update(site.editSiteManager(siteManager));
        }
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#changeStatus(co.fitstart.entity.principal.Principal)
     */
    public void changeStatus(Principal principal) {
        if(principal.isDisabled()) {
            Principal existPrincipal = principalDao.load(principal.getName());
            
            if(existPrincipal != null) {
                throw new BusinessException("已存在账号名为" + principal.getName() + "的账号，不可重启！");
            } else {
                if(principal.isSiteServer()) {
                    PrincipalReportRelation relation = principalDao.getBySiteServer(principal);
                    
                    if(relation == null) {
                        throw new BusinessException("运营账号未指定门店，不可重启！");
                    }
                }else if(principal.isSiteManager()) {
                    PrincipalReportRelation relation = principalDao.getRelation(principal.getId());
                    
                    if(relation == null) {
                        throw new BusinessException("店长账号未指定门店，不可重启！");
                    }
                }
            }
        }
        
        genericDaoSupport.update(principal.changeStatus());
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.PrincipalService#changeSite(co.fitstart.entity.principal.Principal, co.fitstart.entity.site.Site)
     */
    public void changeSite(Principal principal, Site site) {
        if(principal.isSiteManager()) {
            PrincipalReportRelation relation = principalDao.getRelation(principal.getId());
            
            PrincipalReportRelation siteRelation = principalDao.getSiteManager(site);
            
            if(relation == null) {
                if(siteRelation == null) {
                    genericDaoSupport.save(new PrincipalReportRelation(null, principal, site));
                } else {
                    genericDaoSupport.update(siteRelation.editManager(principal));
                }
            } else {
                if(siteRelation != null) {
                    principalDao.deleteSiteManager(siteRelation.getManager());
                }
                
                genericDaoSupport.update(relation.editSite(site));
            }
        } else if(principal.isSiteServer()) {
            PrincipalReportRelation relation = principalDao.getBySiteServer(principal);
            
            if(relation == null) {
                genericDaoSupport.save(new PrincipalReportRelation(principal, null, site));
            } else {
                genericDaoSupport.update(relation.editSite(site));
            }
        }
    }
}
